import json
import pymysql
import requests
import paramiko
from apps.lymonitor.models import MonitorManage, MonitorHis
requests.packages.urllib3.disable_warnings()


class BaseHandler:
    # http 响应数据关键字处理
    def match_key_url(self, key, key_type, data):
        if key_type == "true" and key in data:
            status = 0
        elif key_type == "true" and key not in data:
            status = 1
        elif key_type == "false" and key in data:
            status = 1
        elif key_type == "false" and key not in data:
            status = 0
        else:
            status = 1
        return status

    
    # http请求处理
    def send_request(self, method, url, data=None, key=None, key_type=None, timeout=2, verify=False):
        try:
            response = requests.request(method, url, data=data, verify=verify, timeout=timeout)
            res = response.json()
            status = self.match_key_url(key, key_type, res)
            return {"status": status, "res": res}
        except json.JSONDecodeError:
            res = response.text
            status = self.match_key_url(key, key_type, res)
            return {"status": status, "res": res}
        except Exception as e:
            return {"status": 1, "res": str(e)}

    
    # sql执行
    def run_sql(self, host, port, username, password, database, sql):
        try:
            db = pymysql.connect(host=host, port=port, user=username,password=password,database=database)
            cursor = db.cursor()
            cursor.execute(sql)
            rest = cursor.fetchall()
            db.close()
            return {"status": 0, "res": rest}
        except Exception as e:
            return {"status": 1, "res": str(e)}

    
    # swat 进程监控个性化处理
    def send_process(self, ipaddr, port, username, password, db, sql):
        res = self.run_sql(ipaddr, int(port), username, password, db, sql)
        if res["status"] == 1:
            return res
        monitor_process_info_list = res["res"]
        all_process = []
        status = 0
        for process_info in monitor_process_info_list:
            server_id = process_info[0]
            conn_ip = process_info[1]
            application_name = process_info[3]
            server_name = process_info[2]
            info = process_info[4]
            if "正常" not in info:
                status = 1
            all_process.append({"server_id": server_id, "server_name": server_name, "conn_ip": conn_ip, "application_name": application_name, "info": info, "status": status})
        return {"status": status, "res": all_process}

    # 命令执行
    def execute_remote_command(self, host, username, password, port, cmd):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(host, username=username, port=port, password=password)
            stdin, stdout, stderr = ssh.exec_command(cmd)
            # 读取命令执行结果
            output = stdout.read().decode()
            error = stderr.read().decode()
            if error:
                return {"status": 1, "res": error}
            return {"status": 0, "res": output}
        except paramiko.AuthenticationException as auth_error:
            return {"status": 1, "res": str(auth_error)}
        except paramiko.SSHException as ssh_error:
            return {"status": 1, "res": str(ssh_error)}
        except Exception as e:
            return {"status": 1, "res": str(e)}
        finally:
            ssh.close()



    def match_type(self, info):
        try:
            data = info.monitor_data
            if info.monitor_type == "url":
                return self.send_request(**data)
            elif info.monitor_type == "cmd":
                data["username"] = "admin"
                data["password"] = "Nuq1mI8qmUEehRIeLO"
                data["port"] = 22
                return self.execute_remote_command(**data)
            elif info.monitor_type == "MySQL":
                return self.send_process(**data)
            else:
                return {"status": 1, "res": None}
        except Exception as e:
            return {"status": 1, "res": str(e)}

def main():
    obj = MonitorManage.objects.all()
    for info in obj:
        if info and info.is_alive == 0:
            exe_res = BaseHandler().match_type(info)
            info.status = exe_res["status"]
            MonitorHis.objects.create(name=info.flag, monitor=info, data=json.dumps(exe_res))